package com.studerb.dao;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.SessionImpl;
import org.hibernate.type.Type;
import org.springframework.stereotype.Repository;

import com.studerb.dao.interfaces.IHeaderThreadDao;
import com.studerb.model.Header;
import com.studerb.model.HeaderThread;
import com.studerb.model.NewsGroup;

@Repository public class HeaderThreadDao extends HibSpringDaoImp<HeaderThread> implements IHeaderThreadDao {

	@Override public int deleteByNewsGroup(NewsGroup newsGroup, Long min, Long max) {
		List<Object> args = new ArrayList();
		List<Type> types = new ArrayList();

		args.add(newsGroup.getId());
		types.add(Hibernate.LONG);
		StringBuffer queryString = new StringBuffer("from HeaderThread ht where ht.newsGroup.id = ?");
		if (min != null) {
			queryString.append(" AND ht.articleNumber >= ?");
			args.add(min);
			types.add(Hibernate.LONG);
		}
		if (max != null) {
			queryString.append(" AND ht.articleNumber <= ?");
			args.add(max);
			types.add(Hibernate.LONG);
		}

		Type[] hibTypes = types.toArray(new Type[types.size()]);
		SessionImpl sessionImp = (SessionImpl) getCurrentSession();
		return sessionImp.delete(queryString.toString(), args.toArray(), hibTypes);
	}

	public int deleteByNewsGroup2(NewsGroup newsGroup, Long min, Long max) {
		String queryString;
		Query query = null;
		if (min == null && max == null) {
			queryString = "delete HeaderThread ht where ht.newsGroup.id = :id";
			query = getCurrentSession().createQuery(queryString);
		}
		else if (min == null) {
			queryString = "delete HeaderThread ht where ht.newsGroup.id = :id and ht.articleNumber <= :max";
			query = getCurrentSession().createQuery(queryString).setParameter("max", max);
		}
		else if (max == null) {
			queryString = "delete HeaderThread ht where ht.newsGroup.id = :id and ht.articleNumber >= :min";
			query = getCurrentSession().createQuery(queryString).setParameter("min", min);
		}
		else {
			queryString = "delete HeaderThread ht where ht.newsGroup.id = :id and ht.articleNumber between :min AND :max";
			query = getCurrentSession().createQuery(queryString).setParameter("min", min).setParameter("max", max);
		}
		query.setParameter("id", newsGroup.getId());
		int deleted = query.executeUpdate();
		logger.debug("Deleted " + deleted + " headerThreads for newsgroup: " + newsGroup.getGroupName());
		return deleted;
	}

	@Override public List<Header> getHeadersByThread(HeaderThread headerThread) {
		String queryString = "from Header h where h.headerThread.id = :id order by h.currentPart asc";
		Query query = getCurrentSession().createQuery(queryString);
		query.setParameter("id", headerThread.getId());
		List<Header> headers = query.list();
		logger.debug("fetching all Headers (" + headers.size() + ") for thread with subject: " + headerThread.getSubject());
		return headers;
	}

	@Override public List<HeaderThread> getHeaderThreads(NewsGroup newsGroup, Long min, Long max) {
		Criteria criteria = getCurrentSession().createCriteria(HeaderThread.class);
		criteria.addOrder(Order.asc("articleNumber"));
		criteria.add(Restrictions.eq("newsGroup.id", newsGroup.getId()));
		if (min != null) {
			criteria.add(Restrictions.ge("articleNumber", min));
		}
		if (max != null) {
			criteria.add(Restrictions.le("articleNumber", max));
		}
		List<HeaderThread> headerThreads = criteria.list();
		logger.debug("fetched all (" + headerThreads.size() + ") headerThreads for group: " + newsGroup.getGroupName() + " between numbers: " + min + " / " + max);
		return headerThreads;
	}

	@Override public List<HeaderThread> getIncomplete(NewsGroup newsGroup, Long min, Long max) {
		Criteria criteria = getCurrentSession().createCriteria(HeaderThread.class);
		criteria.addOrder(Order.asc("articleNumber"));
		criteria.add(Restrictions.eq("newsGroup.id", newsGroup.getId()));
		criteria.add(Restrictions.eq("complete", Boolean.FALSE));
		if (min != null) {
			criteria.add(Restrictions.ge("articleNumber", min));
		}
		if (max != null) {
			criteria.add(Restrictions.le("articleNumber", max));
		}
		List<HeaderThread> headerThreads = criteria.list();
		logger.debug("fetched (" + headerThreads.size() + ") incomplete headerThreads for group: " + newsGroup.getGroupName() + " between numbers: " + min + " / " + max);
		return headerThreads;
	}

}
